package com.ofek.applicationbase.model;

import java.lang.reflect.Field;

import com.ofek.applicationbase.broadcast.Broadcaster;
import com.ofek.applicationbase.utils.ReflectionUtils;

public abstract class Model implements IModel {

	private Broadcaster<ModelListener> dataChangeBroadcaster = new Broadcaster<ModelListener>();
	private boolean broadCasting;

	@Override
	public synchronized boolean registerModelChangedListener(ModelListener listener) {
		return dataChangeBroadcaster.register(listener);
	}

	@Override
	public synchronized boolean unregisterModelChangedListener(ModelListener listener) {
		return dataChangeBroadcaster.unregister(listener);
	}

	protected synchronized void broadcast(Model model) {
		if (broadCasting) throw new RuntimeException("Inifinite loop detected");
		broadCasting = true;
		dataChangeBroadcaster.broadcast("onModelChanged",model);
		broadCasting = false;
	}
	protected synchronized boolean set(String fieldName,Object newer,Object older) {
		try {
			Field declaredField = ReflectionUtils.getField(this.getClass(),fieldName);
			boolean hasChanged = false;
			if (newer!=older && ((newer!=null && !newer.equals(older)) || (older!=null && !older.equals(newer)))) 
				hasChanged =true;
			declaredField.setAccessible(true);
			declaredField.set(this, newer);
			if (hasChanged) 
				broadcast(this);
			return hasChanged;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return false;
	}
	protected synchronized boolean set(Object newer,Object older) {
		String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
		String replaceFirst = methodName.replaceFirst("set", "");
		char charAt = replaceFirst.charAt(0);
		replaceFirst = replaceFirst.replaceFirst(""+charAt, ""+Character.toLowerCase(charAt));
		return set(replaceFirst,newer,older);	
	}

}
